﻿using System;
using System.Collections.Generic;
using System.Text;
using Csla;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data.Common;
using Csla.Data;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using buildingLib.security;

namespace buildingLib.fee
{
    /// <summary>
    /// 收费通知单，Invoice表中type字段为5时，表示这是由发送收费通知单所添加的记录
    /// </summary>
    [Serializable()]
    public class FeeNotify : BusinessBase<FeeNotify> ,security.IACL
    {
        #region ACL
        public Guid ACLID
        {
            get { return new Guid("{A84F8CBC-D395-4320-BBB0-5BBBFC4A5ED8}"); }
        }

        public string ACLName
        {
            get { return "收费通知单"; }
        }

        public string ACLCategory
        {
            get { return "客服"; }
        }

        public string ACLDescription
        {
            get { return "业主收费通知单"; }
        }

        public static Guid GetACLID()
        {
            return new Guid("{A84F8CBC-D395-4320-BBB0-5BBBFC4A5ED8}");
        }

        #endregion
        #region Bussiness

        //统计用字段
        public int TicketNum
        {
            get { return m_items.Count; }
        }
        public int ClosedNum
        {
            get {
                int count = 0;
                foreach (FeeNotifyItem item in m_items)
                {
                    if (item.Status == "已完成")
                        count++;
                }
                return count;
            }
        }
        public string NumRate {
            get {
                int count = 0;
                foreach (FeeNotifyItem item in m_items)
                {
                    if (item.Status == "已完成")
                        count++;
                }
                double rate = (double)count / (double)m_items.Count;
                rate = rate * 100;
                return rate.ToString("f2")+"%";
            }
        }


        Guid m_id = Guid.Empty;                 //标识列
        public Guid Id
        {
            get { return m_id; }
        }
        protected override object GetIdValue()
        {
            return m_id;
        }
        string m_creator = String.Empty;        //创建人
        public string Creator
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_creator;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (value == null) value = string.Empty;
                if (m_creator != value)
                {
                    m_creator = value;
                    PropertyHasChanged();
                }
            }
        }
        DateTime m_createdTime = DateTime.Now;  //创建时间
        public DateTime CreatedTime
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_createdTime;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (value == null) value = DateTime.Now;
                if (m_createdTime != value)
                {
                    m_createdTime = value;
                    PropertyHasChanged();
                }
            }
        }
        FeeNotifyItems m_items;
        public FeeNotifyItems Items
        {
            get { return m_items; }  
              
        }
        InvoiceItems templeteItems;
        public InvoiceItems TempleteItems {
            get { return templeteItems; }
            set { templeteItems = value; }
        }
        string m_name = string.Empty;
        public string Name
        {
            get
            {
                CanReadProperty(true);
                return m_name;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (value == null) value =string.Empty;
                if (m_name != value)
                {
                    m_name = value;
                    PropertyHasChanged();
                }
            }
        }
        
        #endregion
        #region Factory
        public static FeeNotify NewFeeNotify()
        {
            return DataPortal.Create<FeeNotify>();
        }

        public static FeeNotify GetNewNotify(Guid id)
        {
            return DataPortal.Fetch<FeeNotify>(id);
        }
        private FeeNotify()
        { }
        #endregion
        #region DataMethod
        protected override void DataPortal_Create()
        {
            m_id = Guid.NewGuid();
            m_creator = Csla.ApplicationContext.User.Identity.Name;
            m_items = FeeNotifyItems.NewFeeNotifyItems();
        }

        protected override void DataPortal_Fetch(object criteria)
        {
            string sql = "SELECT * FROM [FeeNotify] WHERE id = '" + criteria.ToString() + "'";
            Database db = SQLDatabase.GetDatabase();
            DbCommand cmd = db.GetSqlStringCommand(sql);
            using (SafeDataReader dr = new SafeDataReader(db.ExecuteReader(cmd)))
            {
                if (dr.Read())
                {
                    this.m_id = dr.GetGuid("id");
                    m_creator = dr.GetString("creator");
                    m_createdTime = dr.GetDateTime("createdTime");
                    m_items = FeeNotifyItems.GetFeeNotifyItems(m_id, m_id);
                    m_name = dr.GetString("name");
                    
                    //读取二进制内容
                    System.IO.Stream sr = new MemoryStream();
                    int bufLen = 100;
                    byte[] b = new byte[bufLen];
                    BinaryWriter bw = new BinaryWriter(sr);
                    long startIndex = 0;
                    long retval;
                    retval = dr.GetBytes("sdata", startIndex, b, 0, bufLen);
                    while (retval == bufLen)
                    {
                        bw.Write(b);
                        bw.Flush();

                        startIndex += bufLen;
                        retval = dr.GetBytes("sdata", startIndex, b, 0, bufLen);
                    }
                    bw.Write(b);
                    sr.Position = 0;
                    //反序列化
                    BinaryFormatter formatter = new BinaryFormatter();
                    templeteItems = formatter.Deserialize(sr) as InvoiceItems;
                    sr.Close();
                }
            }
        }

        protected override void DataPortal_Insert()
        {
            m_createdTime = DateTime.Now;
            Database db = SQLDatabase.GetDatabase();
            DbCommand cmd = db.GetSqlStringCommand("Insert Into [dbo].[FeeNotify] Values(@id,@sdata,@createdTime,@creator,@name)");
            double result = 0;
            db.AddInParameter(cmd, "id", DbType.Guid, m_id);
            db.AddInParameter(cmd, "createdTime", DbType.DateTime, m_createdTime);
            db.AddInParameter(cmd, "creator", DbType.String, m_creator);
            db.AddInParameter(cmd, "name", DbType.String, m_name);

            //序列化文件
            System.IO.Stream sData = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(sData, templeteItems);
            byte[] bData = new byte[sData.Length];
            sData.Position = 0;
            sData.Read(bData, 0, (int)sData.Length);
            sData.Close();
            db.AddInParameter(cmd, "sdata", DbType.Binary, bData);
            m_items.InsertAll(bData);
            db.ExecuteNonQuery(cmd);
        }
        #endregion
    }

    public class FeeNotifyItems : BusinessListBase<FeeNotifyItems, FeeNotifyItem>
    { 
        #region Factory Method
        private FeeNotifyItems() { }
        public static FeeNotifyItems GetFeeNotifyItems(Guid id,Guid categoryID)
        {
            FeeNotifyItems invoiceTaskList = new FeeNotifyItems();
            invoiceTaskList.Fetch(categoryID);
            return invoiceTaskList;
        }
        
        public static FeeNotifyItems NewFeeNotifyItems()
        {
            return new FeeNotifyItems();
        }
        #endregion

        #region DataAccess
        protected void Fetch(Guid categoryID)
        {
            RaiseListChangedEvents = false;
            this.Clear();
            //查询InvoiceTask表，找到所有Ticket
            string sql = "SELECT id FROM [invoice] WHERE ";
            sql += "CategoryID = '" + categoryID + "' and type = "+(int)FeeSourceType.Schedule;
            Database db = SQLDatabase.GetDatabase();
            DbCommand cmd = db.GetSqlStringCommand(sql);
            using (SafeDataReader dr = new SafeDataReader(db.ExecuteReader(cmd)))
            {
                while(dr.Read())
                    this.Add(FeeNotifyItem.GetFeeNotifyItem(dr.GetGuid(0)));
            }
            RaiseListChangedEvents = true;
        }
        public void InsertAll(byte[] bdata)
        {
            foreach (FeeNotifyItem item in this)
            {
                //item.bData = bdata;
                item.Save();
            }   
        }
        #endregion

        [Serializable()]
        protected class Criteria
        {
            private Guid _id;
            public Guid Id
            {
                get
                { return _id; }
                set
                { _id = value; }
            }
            private Guid _categoryID;
            public Guid CateGoryID
            {
                get
                { return _categoryID; }
                set
                { _categoryID = value; }
            }
        }

    }

    public class FeeNotifyItem : BusinessBase<FeeNotifyItem>
    {
        #region Bussiness

        Guid m_id;
        public Guid ID
        {
            get { return m_id; }
        }
        protected override object GetIdValue()
        {
            return m_id;
        }
        int m_taskStatus;
        public string DoorName
        {
            get
            {
                return DataCaches.GetDoorName(m_doorID);
            }
        }
        bool m_isDel = false;
        string m_Name = string.Empty;
        /// <summary>
        /// 收费单名称
        /// </summary>
        public string Name
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_Name;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (value == null) value = string.Empty;
                if (m_Name != value)
                {
                    m_Name = value;
                    PropertyHasChanged();
                }
            }
        }

        /// <summary>
        /// 收费单的总额
        /// </summary>
        public double Amount
        {

            get
            {
                double result = 0;
                foreach (InvoiceItem item in m_items)
                {
                    result += item.Total;
                }
                return result;
            }

        }

        string m_feeTime = string.Empty;
        /// <summary>
        /// 收费时间，可以不填
        /// </summary>
        public string FeeTime
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_feeTime;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (value == null) value = string.Empty;
                if (m_feeTime != value)
                {
                    m_feeTime = value;
                    PropertyHasChanged();
                }
            }
        }

        SmartDate m_created;
        public string Created
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_created.Text;
            }
        }

        SmartDate m_deadline = new SmartDate();
        /// <summary>
        /// 应缴费截止时间
        /// </summary>
        public DateTime Deadline
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_deadline.Date;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (!m_deadline.Equals(value))
                {
                    m_deadline = new SmartDate(value);
                    PropertyHasChanged();
                }
            }
        }

        SmartDate m_closetime;
        /// <summary>
        /// 维修单缴费时间
        /// </summary>
        public string CloseTime
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_closetime.Text;
            }
        }

        Guid m_doorID;
        /// <summary>
        /// 房间编号，对于非业主费用可能没有房间编号
        /// </summary>
        public Guid DoorID
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_doorID;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (!m_doorID.Equals(value))
                {
                    m_doorID = value;
                    PropertyHasChanged();
                }
            }
        }

        InvoiceItems m_items;
        public InvoiceItems Items
        {
            get { return m_items; }
            set { m_items = value; }
        }

        Guid m_categoryID;
        public Guid CategoryID
        {
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            get
            {
                CanReadProperty(true);
                return m_categoryID;
            }
            [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
            set
            {
                CanWriteProperty(true);
                if (!m_categoryID.Equals(value))
                {
                    m_categoryID = value;
                    PropertyHasChanged();
                }
            }
        }
        public string Status
        {
            get {
                if (m_isDel)
                    return "已作废";
                switch(m_taskStatus)
                {
                    case 0:
                        return "未通知";
                    case 1:
                    case 2:
                        return "未缴费";
                    default:
                        return "已完成";
                }
            }
        }
        //public byte[] bData;
        
        #endregion
        #region Validation Rules
        protected override void AddBusinessRules()
        {
            // TODO: add validation rules
            ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, "Name");
            ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, "FeeTime");
        }
        #endregion
        #region FactoryMethod
        public static FeeNotifyItem NewFeeNotifyItem(Guid doorID, Guid categoryID)
        {
            Criteria c = new Criteria();
            c.CateGoryID = categoryID;
            c.Id = doorID;
            return DataPortal.Create<FeeNotifyItem>(c);
        }

        public static FeeNotifyItem GetFeeNotifyItem(Guid id)
        {
            return DataPortal.Fetch<FeeNotifyItem>(id);
        }

        private FeeNotifyItem()
        { }
        #endregion

        #region DataMethod
        public void DeleteThis()
        {
            if (this.IsNew)
                return;
            string sql = "Update Invoice Set isDel = 1 where id = @id";
            Database db = SQLDatabase.GetDatabase();
            DbCommand dbcom = db.GetSqlStringCommand(sql);
            db.AddInParameter(dbcom, "id", DbType.Guid, m_id);
            db.ExecuteNonQuery(dbcom);

        }
        [RunLocal]
        protected void  DataPortal_Create(object criteria)
        {
            m_id = Guid.NewGuid();
            m_doorID = ((Criteria)criteria).Id;
            m_categoryID = ((Criteria)criteria).CateGoryID;
            m_items = InvoiceItems.NewInvoiceItems();
            m_created = SmartDate.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
        protected override void DataPortal_Insert()
        {
            Database db = SQLDatabase.GetDatabase();
            DbCommand dbcom = db.GetSqlStringCommand(@"insert into invoice (id,amount,doorid,name,feetime,creator,createtime,deadlinetime,sdata,type,categoryid) values 
                    (NEWID(),@amount,@doorid,@name,@feetime,@creator,@createtime,@deadlinetime,@sdata,"+(int)FeeSourceType.Schedule+",@categoryid)");

            db.AddInParameter(dbcom, "amount", DbType.Double, Amount);
            db.AddInParameter(dbcom, "name", DbType.String, Name);
            db.AddInParameter(dbcom, "feetime", DbType.String, FeeTime);
            db.AddInParameter(dbcom, "createtime", DbType.DateTime, m_created.DBValue);
            db.AddInParameter(dbcom, "deadlinetime", DbType.DateTime, m_deadline.DBValue);
            db.AddInParameter(dbcom, "categoryID", DbType.Guid, m_categoryID);
            db.AddInParameter(dbcom, "creator", DbType.String, Csla.ApplicationContext.User.Identity.Name);

            if (DoorID == Guid.Empty)
                db.AddInParameter(dbcom, "doorid", DbType.Guid, null);
            else
                db.AddInParameter(dbcom, "doorid", DbType.Guid, DoorID);
            System.IO.Stream sData = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(sData, m_items);
            byte[] bData = new byte[sData.Length];
            sData.Position = 0;
            sData.Read(bData, 0, (int)sData.Length);
            sData.Close();
            db.AddInParameter(dbcom, "sdata", DbType.Binary, bData);
            //序列化文件

            int roweffected = db.ExecuteNonQuery(dbcom);
        }

        public void UpdateTaskStatus(int status)
        { 
            Database db = SQLDatabase.GetDatabase();
            DbCommand dbcom = db.GetSqlStringCommand("Update invoice_task set status = @status where ticketid=@id");
            db.AddInParameter(dbcom, "@status", DbType.Int32, status);
            db.AddInParameter(dbcom,"id",DbType.Guid,m_id);
            db.ExecuteNonQuery(dbcom);
        }
        private void DataPortal_Fetch(Guid criteria)
        {
            Database db = SQLDatabase.GetDatabase();
            DbCommand dbcom = db.GetSqlStringCommand("select i.id,i.doorid,i.name,i.feetime,i.creator,i.createtime,i.deadlinetime,i.closetime,i.categoryid,i.closer,i.sdata,t.status ,i.isDel from invoice as i left join invoice_task as t on i.id=t.ticketid where i.id=@id");

            db.AddInParameter(dbcom, "id", DbType.Guid, criteria);

            using (SafeDataReader dr = new SafeDataReader(db.ExecuteReader(dbcom)))
            {
                if (dr.Read())
                {
                    m_id = dr.GetGuid("id");
                    m_doorID = dr.GetGuid("doorid");
                    m_Name = dr.GetString("name");
                    m_feeTime = dr.GetString("feetime");
                    m_created = dr.GetSmartDate("createtime");
                    m_deadline = dr.GetSmartDate("deadlinetime");
                    m_closetime = dr.GetSmartDate("closetime");
                    m_categoryID = dr.GetGuid("categoryID");
                    m_taskStatus = dr.GetValue("status") == null?3:dr.GetInt32("Status");
                    m_isDel = dr.GetBoolean("isDel");
                    //读取二进制内容
                    System.IO.Stream sr = new MemoryStream();
                    int bufLen = 100;
                    byte[] b = new byte[bufLen];
                    BinaryWriter bw = new BinaryWriter(sr);
                    long startIndex = 0;
                    long retval;
                    retval = dr.GetBytes("sdata", startIndex, b, 0, bufLen);
                    while (retval == bufLen)
                    {
                        bw.Write(b);
                        bw.Flush();

                        startIndex += bufLen;
                        retval = dr.GetBytes("sdata", startIndex, b, 0, bufLen);
                    }
                    bw.Write(b);
                    sr.Position = 0;
                    //反序列化
                    BinaryFormatter formatter = new BinaryFormatter();
                    m_items = formatter.Deserialize(sr) as InvoiceItems;
                    sr.Close();

                }
            }
        }
        #endregion

        [Serializable()]
        protected class Criteria
        {
            private Guid _id;
            public Guid Id
            {
                get
                { return _id; }
                set
                { _id = value; }
            }
            private Guid _categoryID;
            public Guid CateGoryID
            {
                get
                { return _categoryID; }
                set
                { _categoryID = value; }
            }
        }
    }
    
}
